home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sound / k007232.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  11KB  |  477 lines

  1. /*********************************************************/
  2. /*    Konami PCM controller                              */
  3. /*********************************************************/
  4.  
  5. /*
  6.  
  7.     Changelog, Mish, August 1999:
  8.         Removed interface support for different memory regions per channel.
  9.         Removed interface support for differing channel volume.
  10.  
  11.         Added bankswitching.
  12.         Added support for multiple chips.
  13.  
  14.         (Nb:  Should different memory regions per channel be needed
  15.         the bankswitching function can set this up).
  16.  
  17. NS990821
  18. support for the K007232_VOL() macro.
  19. added external port callback, and functions to set the volume of the channels
  20.  
  21. */
  22.  
  23.  
  24. #include "driver.h"
  25. #include <math.h>
  26.  
  27.  
  28. #define  KDAC_A_PCM_MAX    (2)        /* Channels per chip */
  29.  
  30.  
  31. typedef struct kdacApcm
  32. {
  33.     unsigned char vol[KDAC_A_PCM_MAX][2];    /* volume for the left and right channel */
  34.     unsigned int  addr[KDAC_A_PCM_MAX];
  35.     unsigned int  start[KDAC_A_PCM_MAX];
  36.     unsigned int  step[KDAC_A_PCM_MAX];
  37.     int play[KDAC_A_PCM_MAX];
  38.     int loop[KDAC_A_PCM_MAX];
  39.  
  40.     unsigned char wreg[0x10];    /* write data */
  41.     unsigned char *pcmbuf[2];    /* Channel A & B pointers */
  42.  
  43. } KDAC_A_PCM;
  44.  
  45. static KDAC_A_PCM    kpcm[MAX_K007232];
  46.  
  47. static int pcm_chan[MAX_K007232];
  48.  
  49. static const struct K007232_interface *intf;
  50.  
  51. #define   BASE_SHIFT    (12)
  52.  
  53.  
  54.  
  55. #if 0
  56. static int kdac_note[] = {
  57.   261.63/8, 277.18/8,
  58.   293.67/8, 311.13/8,
  59.   329.63/8,
  60.   349.23/8, 369.99/8,
  61.   392.00/8, 415.31/8,
  62.   440.00/8, 466.16/8,
  63.   493.88/8,
  64.  
  65.   523.25/8,
  66. };
  67.  
  68. static float kdaca_fn[][2] = {
  69.   /* B */
  70.   { 0x03f, 493.88/8 },        /* ?? */
  71.   { 0x11f, 493.88/4 },        /* ?? */
  72.   { 0x18f, 493.88/2 },        /* ?? */
  73.   { 0x1c7, 493.88   },
  74.   { 0x1e3, 493.88*2 },
  75.   { 0x1f1, 493.88*4 },        /* ?? */
  76.   { 0x1f8, 493.88*8 },        /* ?? */
  77.   /* A+ */
  78.   { 0x020, 466.16/8 },        /* ?? */
  79.   { 0x110, 466.16/4 },        /* ?? */
  80.   { 0x188, 466.16/2 },
  81.   { 0x1c4, 466.16   },
  82.   { 0x1e2, 466.16*2 },
  83.   { 0x1f1, 466.16*4 },        /* ?? */
  84.   { 0x1f8, 466.16*8 },        /* ?? */
  85.   /* A */
  86.   { 0x000, 440.00/8 },        /* ?? */
  87.   { 0x100, 440.00/4 },        /* ?? */
  88.   { 0x180, 440.00/2 },
  89.   { 0x1c0, 440.00   },
  90.   { 0x1e0, 440.00*2 },
  91.   { 0x1f0, 440.00*4 },        /* ?? */
  92.   { 0x1f8, 440.00*8 },        /* ?? */
  93.   { 0x1fc, 440.00*16},        /* ?? */
  94.   { 0x1fe, 440.00*32},        /* ?? */
  95.   { 0x1ff, 440.00*64},        /* ?? */
  96.   /* G+ */
  97.   { 0x0f2, 415.31/4 },
  98.   { 0x179, 415.31/2 },
  99.   { 0x1bc, 415.31   },
  100.   { 0x1de, 415.31*2 },
  101.   { 0x1ef, 415.31*4 },        /* ?? */
  102.   { 0x1f7, 415.31*8 },        /* ?? */
  103.   /* G */
  104.   { 0x0e2, 392.00/4 },
  105.   { 0x171, 392.00/2 },
  106.   { 0x1b8, 392.00   },
  107.   { 0x1dc, 392.00*2 },
  108.   { 0x1ee, 392.00*4 },        /* ?? */
  109.   { 0x1f7, 392.00*8 },        /* ?? */
  110.   /* F+ */
  111.   { 0x0d0, 369.99/4 },        /* ?? */
  112.   { 0x168, 369.99/2 },
  113.   { 0x1b4, 369.99   },
  114.   { 0x1da, 369.99*2 },
  115.   { 0x1ed, 369.99*4 },        /* ?? */
  116.   { 0x1f6, 369.99*8 },        /* ?? */
  117.   /* F */
  118.   { 0x0bf, 349.23/4 },        /* ?? */
  119.   { 0x15f, 349.23/2 },
  120.   { 0x1af, 349.23   },
  121.   { 0x1d7, 349.23*2 },
  122.   { 0x1eb, 349.23*4 },        /* ?? */
  123.   { 0x1f5, 349.23*8 },        /* ?? */
  124.   /* E */
  125.   { 0x0ac, 329.63/4 },
  126.   { 0x155, 329.63/2 },        /* ?? */
  127.   { 0x1ab, 329.63   },
  128.   { 0x1d5, 329.63*2 },
  129.   { 0x1ea, 329.63*4 },        /* ?? */
  130.   { 0x1f4, 329.63*8 },        /* ?? */
  131.   /* D+ */
  132.   { 0x098, 311.13/4 },        /* ?? */
  133.   { 0x14c, 311.13/2 },
  134.   { 0x1a6, 311.13   },
  135.   { 0x1d3, 311.13*2 },
  136.   { 0x1e9, 311.13*4 },        /* ?? */
  137.   { 0x1f4, 311.13*8 },        /* ?? */
  138.   /* D */
  139.   { 0x080, 293.67/4 },        /* ?? */
  140.   { 0x140, 293.67/2 },        /* ?? */
  141.   { 0x1a0, 293.67   },
  142.   { 0x1d0, 293.67*2 },
  143.   { 0x1e8, 293.67*4 },        /* ?? */
  144.   { 0x1f4, 293.67*8 },        /* ?? */
  145.   { 0x1fa, 293.67*16},        /* ?? */
  146.   { 0x1fd, 293.67*32},        /* ?? */
  147.   /* C+ */
  148.   { 0x06d, 277.18/4 },        /* ?? */
  149.   { 0x135, 277.18/2 },        /* ?? */
  150.   { 0x19b, 277.18   },
  151.   { 0x1cd, 277.18*2 },
  152.   { 0x1e6, 277.18*4 },        /* ?? */
  153.   { 0x1f2, 277.18*8 },        /* ?? */
  154.   /* C */
  155.   { 0x054, 261.63/4 },
  156.   { 0x12a, 261.63/2 },
  157.   { 0x195, 261.63   },
  158.   { 0x1ca, 261.63*2 },
  159.   { 0x1e5, 261.63*4 },
  160.   { 0x1f2, 261.63*8 },        /* ?? */
  161.  
  162.   { -1, -1 },
  163. };
  164. #endif
  165.  
  166. static float fncode[0x200];
  167. /*************************************************************/
  168. static void KDAC_A_make_fncode( void ){
  169.   int i;
  170. #if 0
  171.   int i, j, k;
  172.   float fn;
  173.   for( i = 0; i < 0x200; i++ )  fncode[i] = 0;
  174.  
  175.   i = 0;
  176.   while( (int)kdaca_fn[i][0] != -1 ){
  177.     fncode[(int)kdaca_fn[i][0]] = kdaca_fn[i][1];
  178.     i++;
  179.   }
  180.  
  181.   i = j = 0;
  182.   while( i < 0x200 ){
  183.     if( fncode[i] != 0 ){
  184.       if( i != j ){
  185.     fn = (fncode[i] - fncode[j]) / (i - j);
  186.     for( k = 1; k < (i-j); k++ )
  187.       fncode[k+j] = fncode[j] + fn*k;
  188.     j = i;
  189.       }
  190.     }
  191.     i++;
  192.   }
  193.  #if 0
  194.      for( i = 0; i < 0x200; i++ )
  195.   logerror("fncode[%04x] = %.2f\n", i, fncode[i] );
  196.  #endif
  197.  
  198. #else
  199.   for( i = 0; i < 0x200; i++ ){
  200.     fncode[i] = (0x200 * 55) / (0x200 - i);
  201. //    logerror("2 : fncode[%04x] = %.2f\n", i, fncode[i] );
  202.   }
  203.  
  204. #endif
  205. }
  206.  
  207.  
  208. /************************************************/
  209. /*    Konami PCM update                         */
  210. /************************************************/
  211.  
  212. static void KDAC_A_update(int chip, INT16 **buffer, int buffer_len)
  213. {
  214.     int i;
  215.  
  216.  
  217.     memset(buffer[0],0,buffer_len * sizeof(INT16));
  218.     memset(buffer[1],0,buffer_len * sizeof(INT16));
  219.  
  220.     for( i = 0; i < KDAC_A_PCM_MAX; i++ )
  221.     {
  222.         if (kpcm[chip].play[i])
  223.         {
  224.             int volA,volB,j,out;
  225.             unsigned int addr, old_addr;
  226.  
  227.             /**** PCM setup ****/
  228.             addr = kpcm[chip].start[i] + ((kpcm[chip].addr[i]>>BASE_SHIFT)&0x000fffff);
  229.             volA = 2 * kpcm[chip].vol[i][0];
  230.             volB = 2 * kpcm[chip].vol[i][1];
  231.             for( j = 0; j < buffer_len; j++ )
  232.             {
  233.                 old_addr = addr;
  234.                 addr = kpcm[chip].start[i] + ((kpcm[chip].addr[i]>>BASE_SHIFT)&0x000fffff);
  235.                 while (old_addr <= addr)
  236.                 {
  237.                     if (kpcm[chip].pcmbuf[i][old_addr] & 0x80)
  238.                     {
  239.                         /* end of sample */
  240.  
  241.                         if (kpcm[chip].loop[i])
  242.                         {
  243.                             /* loop to the beginning */
  244.                             addr = kpcm[chip].start[i];
  245.                             kpcm[chip].addr[i] = 0;
  246.                         }
  247.                         else
  248.                         {
  249.                             /* stop sample */
  250.                             kpcm[chip].play[i] = 0;
  251.                         }
  252.                         break;
  253.                     }
  254.  
  255.                     old_addr++;
  256.                 }
  257.  
  258.                 if (kpcm[chip].play[i] == 0)
  259.                     break;
  260.  
  261.                 kpcm[chip].addr[i] += kpcm[chip].step[i];
  262.  
  263.                 out = (kpcm[chip].pcmbuf[i][addr] & 0x7f) - 0x40;
  264.  
  265.                 buffer[0][j] += out * volA;
  266.                 buffer[1][j] += out * volB;
  267.             }
  268.         }
  269.     }
  270. }
  271.  
  272.  
  273. /************************************************/
  274. /*    Konami PCM start                          */
  275. /************************************************/
  276. int K007232_sh_start(const struct MachineSound *msound)
  277. {
  278.     int i,j;
  279.  
  280.     intf = msound->sound_interface;
  281.  
  282.     /* Set up the chips */
  283.     for (j=0; j<intf->num_chips; j++)
  284.     {
  285.         char buf[2][40];
  286.         const char *name[2];
  287.         int vol[2];
  288.  
  289.         kpcm[j].pcmbuf[0] = (unsigned char *)memory_region(intf->bank[j]);
  290.         kpcm[j].pcmbuf[1] = (unsigned char *)memory_region(intf->bank[j]);
  291.  
  292.         for( i = 0; i < KDAC_A_PCM_MAX; i++ )
  293.         {
  294.             kpcm[j].start[i] = 0;
  295.             kpcm[j].step[i] = 0;
  296.             kpcm[j].play[i] = 0;
  297.             kpcm[j].loop[i] = 0;
  298.         }
  299.         kpcm[j].vol[0][0] = 255;    /* channel A output to output A */
  300.         kpcm[j].vol[0][1] = 0;
  301.         kpcm[j].vol[1][0] = 0;
  302.         kpcm[j].vol[1][1] = 255;    /* channel B output to output B */
  303.  
  304.         for( i = 0; i < 0x10; i++ )  kpcm[j].wreg[i] = 0;
  305.  
  306.         for (i = 0;i < 2;i++)
  307.         {
  308.             name[i] = buf[i];
  309.             sprintf(buf[i],"007232 #%d Ch %c",j,'A'+i);
  310.         }
  311.  
  312.         vol[0]=intf->volume[j] & 0xffff;
  313.         vol[1]=intf->volume[j] >> 16;
  314.  
  315.         pcm_chan[j] = stream_init_multi(2,name,vol,Machine->sample_rate,
  316.                 j,KDAC_A_update);
  317.     }
  318.  
  319.     KDAC_A_make_fncode();
  320.  
  321.     return 0;
  322. }
  323.  
  324. /************************************************/
  325. /*    Konami PCM write register                 */
  326. /************************************************/
  327. static void K007232_WriteReg( int r, int v, int chip )
  328. {
  329.     int  data;
  330.  
  331.     if (Machine->sample_rate == 0) return;
  332.  
  333.     stream_update(pcm_chan[chip],0);
  334.  
  335.     kpcm[chip].wreg[r] = v;            /* stock write data */
  336.  
  337.     if (r == 0x05)
  338.     {
  339.         if (kpcm[chip].start[0] < 0x20000)
  340.         {
  341.             kpcm[chip].play[0] = 1;
  342.             kpcm[chip].addr[0] = 0;
  343.         }
  344.     }
  345.     else if (r == 0x0b)
  346.     {
  347.         if (kpcm[chip].start[1] < 0x20000)
  348.         {
  349.             kpcm[chip].play[1] = 1;
  350.             kpcm[chip].addr[1] = 0;
  351.         }
  352.     }
  353.     else if (r == 0x0d)
  354.     {
  355.         /* select if sample plays once or looped */
  356.         kpcm[chip].loop[0] = v & 0x01;
  357.         kpcm[chip].loop[1] = v & 0x02;
  358.         return;
  359.     }
  360.     else if (r == 0x0c)
  361.     {
  362.         /* external port, usually volume control */
  363.         if (intf->portwritehandler[chip]) (*intf->portwritehandler[chip])(v);
  364.         return;
  365.     }
  366.     else
  367.     {
  368.         int  reg_port;
  369.  
  370.         reg_port = 0;
  371.         if (r >= 0x06)
  372.         {
  373.             reg_port = 1;
  374.             r -= 0x06;
  375.         }
  376.  
  377.         switch (r)
  378.         {
  379.             case 0x00:
  380.             case 0x01:
  381.                 /**** address step ****/
  382.                 data = (((((unsigned int)kpcm[chip].wreg[reg_port*0x06 + 0x01])<<8)&0x0100) | (((unsigned int)kpcm[chip].wreg[reg_port*0x06 + 0x00])&0x00ff));
  383.                 #if 0
  384.                 if( !reg_port && r == 1 )
  385.                 logerror("%04x\n" ,data );
  386.                 #endif
  387.  
  388.                 kpcm[chip].step[reg_port] =
  389.                     ( (7850.0 / (float)Machine->sample_rate) ) *
  390.                     ( fncode[data] / (440.00/2) ) *
  391.                     ( (float)3580000 / (float)4000000 ) *
  392.                     (1<<BASE_SHIFT);
  393.                 break;
  394.  
  395.             case 0x02:
  396.             case 0x03:
  397.             case 0x04:
  398.                 /**** start address ****/
  399.                 kpcm[chip].start[reg_port] =
  400.                     ((((unsigned int)kpcm[chip].wreg[reg_port*0x06 + 0x04]<<16)&0x00010000) |
  401.                     (((unsigned int)kpcm[chip].wreg[reg_port*0x06 + 0x03]<< 8)&0x0000ff00) |
  402.                     (((unsigned int)kpcm[chip].wreg[reg_port*0x06 + 0x02]    )&0x000000ff));
  403.             break;
  404.         }
  405.     }
  406. }
  407.  
  408. /************************************************/
  409. /*    Konami PCM read register                  */
  410. /************************************************/
  411. static int K007232_ReadReg( int r, int chip )
  412. {
  413.     if (r == 0x05)
  414.     {
  415.         if (kpcm[chip].start[0] < 0x20000)
  416.         {
  417.             kpcm[chip].play[0] = 1;
  418.             kpcm[chip].addr[0] = 0;
  419.         }
  420.     }
  421.     else if (r == 0x0b)
  422.     {
  423.         if (kpcm[chip].start[1] < 0x20000)
  424.         {
  425.             kpcm[chip].play[1] = 1;
  426.             kpcm[chip].addr[1] = 0;
  427.         }
  428.     }
  429.     return 0;
  430. }
  431.  
  432. /*****************************************************************************/
  433.  
  434. WRITE_HANDLER( K007232_write_port_0_w )
  435. {
  436.     K007232_WriteReg(offset,data,0);
  437. }
  438.  
  439. READ_HANDLER( K007232_read_port_0_r )
  440. {
  441.     return K007232_ReadReg(offset,0);
  442. }
  443.  
  444. WRITE_HANDLER( K007232_write_port_1_w )
  445. {
  446.     K007232_WriteReg(offset,data,1);
  447. }
  448.  
  449. READ_HANDLER( K007232_read_port_1_r )
  450. {
  451.     return K007232_ReadReg(offset,1);
  452. }
  453.  
  454. WRITE_HANDLER( K007232_write_port_2_w )
  455. {
  456.     K007232_WriteReg(offset,data,2);
  457. }
  458.  
  459. READ_HANDLER( K007232_read_port_2_r )
  460. {
  461.     return K007232_ReadReg(offset,2);
  462. }
  463.  
  464. void K007232_bankswitch(int chip,unsigned char *ptr_A,unsigned char *ptr_B)
  465. {
  466.     kpcm[chip].pcmbuf[0] = ptr_A;
  467.     kpcm[chip].pcmbuf[1] = ptr_B;
  468. }
  469.  
  470. void K007232_set_volume(int chip,int channel,int volumeA,int volumeB)
  471. {
  472.     kpcm[chip].vol[channel][0] = volumeA;
  473.     kpcm[chip].vol[channel][1] = volumeB;
  474. }
  475.  
  476. /*****************************************************************************/
  477.